package org.com.system.util.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.com.system.util.model.ActionValues;
import org.com.system.util.model.Dao;
import org.com.system.util.model.Page;
import org.com.system.util.sql.DeleteSQLGener;
import org.com.system.util.sql.SelectSQLGener;
import org.com.system.util.sql.InsertSQLGener;
import org.com.system.util.sql.UpdateSQLGener;
import org.com.system.util.utils.CollectionUtils;
import org.com.system.util.utils.ModelUtils;
import org.com.system.util.utils.StrUtils;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
 * 该类暂时只实现mysql数据库,如有其它数据库类型请再实现。
 * @author Gandilong
 */
@Repository
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
public class SpringDao<E> implements Dao<E>{

	private static NamedParameterJdbcTemplate nJdbcTemplate=null;
	private static JdbcTemplate jdbcTemplate=null;
	private Logger logger=Logger.getLogger(this.getClass());
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(E entity) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=InsertSQLGener.saveParamsSQL(entity.getClass());
		nJdbcTemplate.update(sql,new BeanPropertySqlParameterSource(entity));
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}

	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(List<E> entitys) {
		for(E entity:entitys){
			save(entity);
		}
	}

	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(ActionValues<String,Object> values, Class<E> entityClass) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=InsertSQLGener.saveValuesSQL(values,entityClass);
		jdbcTemplate.update(sql);
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(List<ActionValues<String,Object>> values,Class<E> entityClass){
		for(ActionValues<String,Object> entity:values){
			save(entity,entityClass);
		}
	}
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(ActionValues<String,Object> values, Class<E> entityClass) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=DeleteSQLGener.deleteSQL(values, entityClass);
		jdbcTemplate.execute(sql);
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}

	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(String id, Class<E> entityClass) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=DeleteSQLGener.deleteSQL(id, entityClass);
		jdbcTemplate.execute(sql);
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
    public void delete(E entity) {
    	long currentTime=StrUtils.printTime("Execute start :");
    	String sql=DeleteSQLGener.deleteSQL(entity,entity.getClass());
    	if(StrUtils.isNotEmpty(sql)){
		    jdbcTemplate.execute(sql);
    	}else{
    		StrUtils.out("Executing Delete method ,But ID 值无效");
    	}
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}

	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(List<E> entitys) {
		if(null!=entitys&&entitys.size()>0){
			for(E entity:entitys){
				delete(entity);
			}
		}
	}

	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(List<String> ids, Class<E> entityClass) {
		if(CollectionUtils.isNotEmpty(ids)){
			for(String id:ids){
				delete(id, entityClass);
			}
		}
	}
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public E get(ActionValues<String,Object> values, Class<E> entityClass) {
		E entity=null;
		if(values.isNotEmpty("id")){
			entity=get(values.getString("id"), entityClass);
		}
		return entity;
	}

	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public E get(String id, Class<E> entityClass) {
		E entity=null;
		String sql=SelectSQLGener.getSQL(id,entityClass);
		final Class<E> modelClass=entityClass;
		long currentTime=StrUtils.printTime("Execute start :");
		List<E> list=jdbcTemplate.query(sql, new RowMapper<E>(){
			public E mapRow(ResultSet result, int index) throws SQLException {
				return (E)ModelUtils.copyFromResult(result, modelClass);
			}
		});
		
		if(CollectionUtils.isNotEmpty(list)){
			entity=list.get(0);
		}
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
		return entity;
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(ActionValues<String,Object> values, Class<E> entityClass) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=SelectSQLGener.listSQL(values,entityClass);
	    logger.info("Execute SQL:"+sql.toLowerCase());
		final Class<E> modelClass=entityClass;
		List<E> list=nJdbcTemplate.query(sql, values, new RowMapper<E>(){
			public E mapRow(ResultSet result, int index) throws SQLException {
				return (E)ModelUtils.copyFromResult(result, modelClass);
			}
		});
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
		return list;
	}
	
	
	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(Class<E> entityClass) {
		final Class<E> modelClass=entityClass;
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=SelectSQLGener.listSQL(entityClass);
		List<E> list=jdbcTemplate.query(sql, new RowMapper<E>(){
			public E mapRow(ResultSet result, int index) throws SQLException {
				return (E)ModelUtils.copyFromResult(result, modelClass);
			}
		});
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
		return list;
	}

	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(Class<E> entityClass,Page page) {
		final Class<E> modelClass=entityClass;
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=SelectSQLGener.listSQL(entityClass,page);
		List<E> list=jdbcTemplate.query(sql, new RowMapper<E>(){
			public E mapRow(ResultSet result, int index) throws SQLException {
				return (E)ModelUtils.copyFromResult(result, modelClass);
			}
		});
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
		return list;
	}

	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(ActionValues<String, Object> values,Class<E> entityClass, Page page) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=SelectSQLGener.listSQL(values,entityClass,page);
		final Class<E> modelClass=entityClass;
		List<E> list=nJdbcTemplate.query(sql,values,new RowMapper<E>(){
			public E mapRow(ResultSet result, int index) throws SQLException {
				return (E)ModelUtils.copyFromResult(result, modelClass);
			}
		});
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
		return list;
	}
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(ActionValues<String,Object> values, Class<E> entityClass) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=UpdateSQLGener.updateValuesSQL(values,entityClass);
		jdbcTemplate.update(sql);
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(List<ActionValues<String,Object>> values,Class<E> entityClass){
		for(ActionValues<String,Object> map:values){
			update(map,entityClass);
		}
	}
	
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
    public void update(E entity) {
		long currentTime=StrUtils.printTime("Execute start :");
		String sql=UpdateSQLGener.updateParamsSQL(entity.getClass());
		nJdbcTemplate.update(sql,new BeanPropertySqlParameterSource(entity));
		StrUtils.D_value(currentTime, StrUtils.printTime("Execute end :"),"Execute time : ");
	}
    
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(List<E> entitys) {
		if(CollectionUtils.isNotEmpty(entitys)){
			for(E entity:entitys){
				update(entity);
			}
		}
	}
	/**
	 * 自动装配DataSource
	 * @param dataSource
	 */
	@Autowired
    public void setDataSource(@Qualifier("dataSource_system")DataSource dataSource) {
        jdbcTemplate = new JdbcTemplate(dataSource);
        nJdbcTemplate=new NamedParameterJdbcTemplate(dataSource);
    }

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

}
